Java, by default: (i) receives bytecode (for example, bytecode received from a Java compiler); (ii) interprets the bytecode into native machine language using a Java Virtual Machine (JVM) interpreter; and (iii) executes the native machine language code. A line-by-line type interpreter reads the bytecode line-by-line and translates the bytecode to native machine code as each line of bytecode is being executed by an operating system. To improve software performance, modern JVMs include a Just-in-Time (JIT) compiler. A JIT compiler translates byte code on a method-by-method basis, or a frequently-executed-instruction-sequence-by-frequently-executed-instruction-sequence basis. JIT translation typically executes faster than line-by-line translation. JIT compilers also perform optimizations to further increase performance, one of which is referred to as ‘inlining,’ where the JIT compiler replaces a method call with an intermediate representation of the target method.
During compilation of a Java method, a JIT compiler may make assumptions about the program being executed to simplify the code (simplifying assumptions) and increase overall performance. For example, the JIT compiler may assume that a final field is never written, that a given method is not overridden, or any number of other simplifying assumptions. Making these simplifying assumptions allows the JIT compiler to generate a more efficient native implementation. For each assumption, the JIT compiler also generates code to handle situations if the assumption is violated (not correct) at runtime.
JVMs also employ a runtime execution mode referred to as Hot Code Replace (HCR). HCR is a JVM execution mode where the executing program or an external agent attached to the JVM is allowed to redefine classes at runtime. HCR requires that when a class is redefined, the ‘shape’ of the class remains constant (fields and methods cannot be added and removed, for example), but the bytecode contents of methods can be changed. This mode is often used to allow editors to dynamically update the implementation of executing methods and as a means of building performance profiling tools.